/*
 * @(#)org.example.groupchat 2020/3/26/0026
 *
 * Copy Right@ 人人译视界
 */


package org.example.groupchat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * <pre>
 * @author tuwei
 *
 * @version 0.9
 *
 * 修改版本: 0.9
 * 修改日期: 2020/3/26/0026
 * 修改人 :  tuwei
 * 修改说明: 初步完成
 * 复审人 ：
 * </pre>
 */
public class GroupChatServer {
	private Selector selector;
	private ServerSocketChannel serverSocketChannel;
	private static final int PORT = 6667;


	public GroupChatServer() {
		try {
			selector = Selector.open();
			serverSocketChannel = ServerSocketChannel.open();
			serverSocketChannel.socket().bind(new InetSocketAddress(PORT));

			serverSocketChannel.configureBlocking(false);
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void listen() {

		try {
			while (true) {
				int count = selector.select();
				if (count > 0) {
					Iterator<SelectionKey> ite = selector.selectedKeys().iterator();
					while (ite.hasNext()) {
						SelectionKey key = ite.next();
						if (key.isAcceptable()) {
							SocketChannel accept = serverSocketChannel.accept();
							accept.configureBlocking(false);
							accept.register(selector, SelectionKey.OP_READ);
							System.out.println(accept.getRemoteAddress() + "上线了");
						}
						if (key.isReadable()) {
							readData(key);
						}
						ite.remove();
					}
				} else {
					System.out.print("等待中...");
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void readData(SelectionKey key) {
		SocketChannel channel = null;
		try {
			channel = (SocketChannel) key.channel();
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			int read = channel.read(buffer);
			if (read > 0) {
				String msg = new String(buffer.array());
				System.out.println("客户端消息：" + msg);
				sendToOtherClients(msg, channel);
			}
		} catch (IOException e) {
			try {
				System.out.println(channel.getRemoteAddress() + "离线了");
				// 取消注册
				key.cancel();
				channel.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}

	private void sendToOtherClients(String msg, SocketChannel self) throws IOException {
		System.out.println("服务器转发消息中...");
		Set<SelectionKey> keys = selector.keys();
		for (SelectionKey key : keys) {
			Channel channel = key.channel();
			if (channel instanceof SocketChannel && !channel.equals(self)) {
				SocketChannel dstChannel = (SocketChannel) channel;
				dstChannel.write(ByteBuffer.wrap(msg.getBytes()));
			}
		}
	}

	public static void main(String[] args) {
		GroupChatServer groupChatServer = new GroupChatServer();
		groupChatServer.listen();
	}
}
